package com.wh.hotel.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.wh.common.annotation.MyAsync;
import com.wh.hotel.convert.HotelStructConvert;
import com.wh.hotel.dao.HotelBookRuleDao;
import com.wh.hotel.dao.HotelRoomTypeDao;
import com.wh.hotel.enums.CancelTypeEnum;
import com.wh.hotel.enums.GuaranteeTypeEnum;
import com.wh.hotel.enums.PayWayEnum;
import com.wh.hotel.model.HotelBookRule;
import com.wh.hotel.model.HotelRoomType;
import com.wh.hotel.response.HotelBookRuleResponse;
import com.wh.hotel.service.HotelBookRuleService;
import com.wh.hotel.service.HotelRoomTypeGoodsService;
import com.wh.hotel.util.PageResultUtil;
import com.wh.hotel.vo.HotelBookRuleVo;
import com.wh.hotel.vo.PayWayRuleVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author luweije
 */
@Slf4j
@Service
public class HotelBookRuleServiceImpl implements HotelBookRuleService {

    @Resource
    private HotelBookRuleDao hotelBookRuleDao;

    @Resource
    private HotelStructConvert hotelStructConvert;

    @Resource
    private HotelRoomTypeGoodsService hotelRoomTypeGoodsService;

    @Resource
    private HotelRoomTypeDao hotelRoomTypeDao;

    @Override
    public IPage<HotelBookRuleResponse> queryPageList(HotelBookRuleVo hotelBookRuleVo) {
        IPage<HotelBookRule> hotelBookRulePage = hotelBookRuleDao.selectPage(hotelBookRuleVo);
        IPage<HotelBookRuleResponse> result = new Page<>();
        PageResultUtil.copyPageInfo(hotelBookRulePage, result);
        result.setRecords(hotelBookRulePage.getRecords().stream()
                .map(hotelBookRule -> hotelStructConvert.convertToHotelBookRuleResponse(hotelBookRule))
                .collect(Collectors.toList())
        );
        return result;
    }

    @Override
    public HotelBookRuleResponse detail(HotelBookRuleVo hotelBookRuleVo) {
        List<HotelBookRule> hotelBookRuleList = hotelBookRuleDao.selectBatchIds(Lists.newArrayList(hotelBookRuleVo.getId()));
        if (CollectionUtils.isEmpty(hotelBookRuleList)) {
            return null;
        }
        return hotelStructConvert.convertToHotelBookRuleResponse(hotelBookRuleList.get(0));
    }

    @Override
    public HotelBookRule saveBookRule(HotelBookRuleVo hotelBookRuleVo) {
        for (PayWayRuleVo payWayRuleVo : hotelBookRuleVo.getPayWayRuleVoList()) {
            Preconditions.checkNotNull(PayWayEnum.parse(payWayRuleVo.getPayWay()), "不支持当前的支付方式");
            if (payWayRuleVo.getGuaranteeType() != null) {
                Preconditions.checkNotNull(GuaranteeTypeEnum.parse(payWayRuleVo.getGuaranteeType()), "不支持当前的担保规则");
            }
            Preconditions.checkNotNull(CancelTypeEnum.parse(payWayRuleVo.getCancelType()), "不支持当前的取消规则");
            if (payWayRuleVo.getCancelType() == CancelTypeEnum.LIMIT_TIME.getCode()) {
                Preconditions.checkNotNull(payWayRuleVo.getFreeCancelMinuteForStart(), "限时取消必须填相对时间");
            }
        }
        if (CollectionUtils.isEmpty(hotelBookRuleVo.getBreakfastNumList())) {
            hotelBookRuleVo.setBreakfastNumList(Lists.newArrayList(0));
        }
        for (Integer breakfastNum : hotelBookRuleVo.getBreakfastNumList()) {
            Preconditions.checkArgument(breakfastNum >= 0, "早餐份数不能小于0");
        }
        HotelBookRule hotelBookRule = hotelStructConvert.convertToHotelBookRule(hotelBookRuleVo);
        if (hotelBookRuleVo.getId() == null) {
            // 新增
            Preconditions.checkArgument(hotelBookRuleDao.insert(hotelBookRule), "新增预订规则失败");
            return hotelBookRule;
        }
        // 修改
        hotelBookRule.setId(hotelBookRuleVo.getId());
        Preconditions.checkArgument(hotelBookRuleDao.update(hotelBookRule), "修改预订规则失败");
        List<HotelRoomType> hotelRoomTypeList = hotelRoomTypeDao.selectByRuleId(hotelBookRule.getId());
        for (HotelRoomType hotelRoomType : hotelRoomTypeList) {
            hotelRoomTypeGoodsService.updateGoodsForRuleChange(hotelRoomType.getId(), hotelBookRule);
        }
        return hotelBookRule;
    }
}
